#ifndef GAMEENGINE_GEOMETRY_VECTOR3D_H
#define GAMEENGINE_GEOMETRY_VECTOR3D_H

#include <GameEngine/Geometry/geometry_settings.h>

#include <GameEngine/Geometry/Location/point3d.h>



#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

//! Class used to represent 3D vectors
/*!
 @note A 3D vector is made of three coordinates, typically
       named x, y and z. The coordinates are of type T,
	   which allows client code to choose the level of
	   precision (typically, T will be either float or
	   double)
 @todo Setup unit tests
 @sa The Vector2d class that handles 2D vectors, and the Point3d class that
     handles 3D points.
 */
template <class T>
class Vector3d : public Point3d<T> {

public:
	Vector3d();
	Vector3d(const T& x, const T& y, const T& z);
	Vector3d(const Point3d<T>& origin, const Point3d<T>& destination);
	template <class R> Vector3d(const Point3d<R>& rhs);
	Vector3d(const Vector3d& rhs);
	virtual ~Vector3d();
	Vector3d& operator=(const Vector3d& rhs);

	Vector3d& operator+=(const Vector3d& rhs);
	Vector3d& operator-=(const Vector3d& rhs);
	Vector3d& operator*=(const Vector3d& rhs);
	Vector3d operator+(const Vector3d& rhs) const;
	Vector3d operator-(const Vector3d& rhs) const;
	Vector3d operator*(const Vector3d& rhs) const;

	template <class R> Vector3d& operator+=(const Vector3d<R>& rhs);
	template <class R> Vector3d& operator-=(const Vector3d<R>& rhs);
	template <class R> Vector3d& operator*=(const Vector3d<R>& rhs);
	template <class R> Vector3d operator+(const Vector3d<R>& rhs) const;
	template <class R> Vector3d operator-(const Vector3d<R>& rhs) const;
	template <class R> Vector3d operator*(const Vector3d<R>& rhs) const;

	template <class R> Vector3d& operator*=(const R& rhs);
	template <class R> Vector3d& operator/=(const R& rhs);

	template <class R> Vector3d operator*(const R& rhs) const;
	template <class R> Vector3d operator/(const R& rhs) const;
	template <class R, class T> friend Vector3d<T> operator*(const R& lhs, const Vector3d<T>& rhs);
	template <class R, class T> friend Vector3d<T> operator/(const R& lhs, const Vector3d<T>& rhs);

	static T dot(const Vector3d& v0, const Vector3d& v1);
	T dot(const Vector3d& rhs) const;
	static Vector3d cross(const Vector3d& v0, const Vector3d& v1);
	Vector3d cross(const Vector3d& rhs) const;

	static bool collinear(const Vector3d& v0, const Vector3d& v1, const T& tolerance = 0.000001);
	bool collinear(const Vector3d& rhs, const T& tolerance = 0.000001) const;

	Vector3d& normalize();
	Vector3d normalize() const;

	T square_length() const;
	T length() const;
};

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#include <GameEngine/Geometry/Location/vector3d.hpp>

#endif
